package api

import (
	"context"
	"github.com/dgrijalva/jwt-go"
	"github.com/gin-gonic/gin"
	"github.com/go-playground/validator/v10"
	"go.uber.org/zap"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/status"
	"net/http"
	"shop_webs/user_web/forms"
	"shop_webs/user_web/global"
	"shop_webs/user_web/middlewares"
	"shop_webs/user_web/models"
	"shop_webs/user_web/proto"
	"shop_webs/user_web/response"
	"strconv"
	"strings"
	"time"
)

func HandleGrpcErrorToHttp(err error, c *gin.Context) {
	if err != nil {
		if status, ok := status.FromError(err); ok {
			switch status.Code() {
			case codes.NotFound:
				c.JSON(http.StatusNotFound, gin.H{
					"msg": status.Message(),
				})
			case codes.Internal:
				c.JSON(http.StatusInternalServerError, gin.H{
					"msg": "内部错误",
				})
			case codes.InvalidArgument:
				c.JSON(http.StatusBadRequest, gin.H{
					"msg": "参数错误",
				})
			case codes.Unavailable:
				c.JSON(http.StatusInternalServerError, gin.H{
					"msg": "用户服务不可用",
				})
			default:
				c.JSON(http.StatusInternalServerError, gin.H{
					"msg": status.Message(),
				})
			}
			return
		}
	}
}
func HandleValidatorError(err error, c *gin.Context) {
	errs, ok := err.(validator.ValidationErrors)
	if !ok {
		c.JSON(http.StatusOK, gin.H{
			"msg": err.Error(),
		})
		return
	}
	c.JSON(http.StatusBadRequest, gin.H{
		"msg": removeTopStruct(errs.Translate(global.Trans)),
		//"msg": errs.Translate(global.Trans),
	})
	return
}

func removeTopStruct(fileds map[string]string) map[string]string {
	rsp := map[string]string{}
	for field, err := range fileds {
		rsp[field[strings.Index(field, ".")+1:]] = err
	}
	return rsp
}
func GetUserList(ctx *gin.Context) {
	zap.S().Infoln("访问用户：", ctx.GetInt("userId"))

	pn := ctx.DefaultQuery("pn", "0")
	pnInt, _ := strconv.Atoi(pn)
	pSize := ctx.DefaultQuery("psize", "10")
	pSizeInt, _ := strconv.Atoi(pSize)

	rsp, err := global.UserSrvClient.GetUserList(ctx, &proto.PageInfo{
		Pn:    uint32(pnInt),
		PSize: uint32(pSizeInt),
	})
	if err != nil {
		zap.S().Errorw("[GetUserList] 查询 【用户列表】失败", "msg", err.Error())
		HandleGrpcErrorToHttp(err, ctx)
		return
	}

	result := make([]interface{}, 0)
	for _, value := range rsp.Data {
		user := response.UserResponse{
			Id:       value.Id,
			NickName: value.NickName,
			Birthday: response.JsonTime(time.Unix(int64(value.BirthDay), 0)),
			Gender:   value.Gender,
			Mobile:   value.Mobile,
		}
		result = append(result, user)
	}
	ctx.JSON(http.StatusOK, result)
}

func PassWordLogin(c *gin.Context) {
	//表单验证
	passWordLoginForm := forms.PassWordLoginForm{}
	if err := c.ShouldBind(&passWordLoginForm); err != nil {
		HandleValidatorError(err, c)
		return
	}
	//if store.Verify(passWordLoginForm.CaptchaId, passWordLoginForm.Captcha, false) {
	//	c.JSON(http.StatusBadRequest, gin.H{
	//		"captcha": "验证码错误",
	//	})
	//	return
	//}

	rsp, err := global.UserSrvClient.GetUserByMobile(context.Background(), &proto.MobileRequest{Mobile: passWordLoginForm.Mobile})
	if err != nil {
		HandleGrpcErrorToHttp(err, c)
		return
	}
	passRsp, pasErr := global.UserSrvClient.CheckPassword(context.Background(), &proto.PasswordCheckInfo{
		PassWord:          passWordLoginForm.PassWord,
		EncryptedPassword: rsp.PassWord,
	})
	if pasErr != nil {
		zap.S().Errorw("[PassWordLogin]:", pasErr.Error())
		c.JSON(http.StatusInternalServerError, map[string]string{
			"password": "登陆失败",
		})
		return
	}
	if passRsp.Success {
		//生成token
		myClaims := models.MyClaims{
			ID:          uint(rsp.Id),
			NickName:    rsp.NickName,
			AuthorityId: uint(rsp.Role),
			StandardClaims: jwt.StandardClaims{
				NotBefore: time.Now().Unix(), //token的生成时间
				ExpiresAt: time.Now().Unix() + 60*60*24,
				Issuer:    "imooc",
			},
		}
		j := middlewares.NewJWT() //有key
		token, err := j.CreateToken(&myClaims)
		if err != nil {
			zap.S().Errorw("[PassWordLogin]:", err.Error())
			c.JSON(http.StatusInternalServerError, gin.H{
				"msg": "生成token失败",
			})
			return
		}
		c.JSON(http.StatusOK, gin.H{
			"id":         rsp.Id,
			"nick_name":  rsp.NickName,
			"token":      token,
			"expired_at": myClaims.StandardClaims.ExpiresAt,
		})
	} else {
		c.JSON(http.StatusBadRequest, map[string]string{
			"msg": "登陆失败",
		})
	}
}
func Register(c *gin.Context) {
	registerForm := forms.RegisterForm{}
	if err := c.ShouldBind(&registerForm); err != nil {
		HandleValidatorError(err, c)
		return
	}
	rsp, err := global.UserSrvClient.CreateUser(context.Background(), &proto.CreateUserInfo{
		NickName: "",
		PassWord: registerForm.PassWord,
		Mobile:   registerForm.Mobile,
	})
	if err != nil {
		zap.S().Errorf("[Register] 查询 【新建用户失败】失败: %s\n", err.Error())
		HandleGrpcErrorToHttp(err, c)
		return
	}

	//生成token
	j := middlewares.NewJWT() //有key
	myClaims := models.MyClaims{
		ID:          uint(rsp.Id),
		NickName:    rsp.NickName,
		AuthorityId: uint(rsp.Role),
		StandardClaims: jwt.StandardClaims{
			NotBefore: time.Now().Unix(), //token的生成时间
			ExpiresAt: time.Now().Unix() + 60*60*24,
			Issuer:    "imooc",
		},
	}
	token, err := j.CreateToken(&myClaims)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{
			"msg": "生成token失败",
		})
		return
	}
	data := map[string]interface{}{
		"id":         rsp.Id,
		"nick_name":  rsp.NickName,
		"token":      token,
		"expired_at": myClaims.StandardClaims.ExpiresAt,
	}
	c.JSON(http.StatusOK, gin.H{
		"data": data,
	})
}
